TI_GDT equ 0
RPL0 equ 0
SELECTOR_VIDEO equ (0x0003<<3)+TI_GDT+RPL0

section .data
put_int_buffer dq 0 ; 数字转字符8字节缓冲区

[bits 32]
section .text

global put_char
global put_str
global put_int
global set_cursor

; 将小端字节序的数字变成对应的ascII后，倒置
; 输入：栈中参数为待打印的数字
; 输出：在屏幕上打印16进制数字，不打印0x前缀
; 例，输入15，打印f
put_int:
	pushad
	mov ebp, esp
	mov eax, [ebp+4*9]
	mov edx, eax
	mov edi, 7
	mov ecx, 8
	mov ebx, put_int_buffer

.16based_4bits:
	and edx, 0x0000000f
	cmp edx, 9
	jg .is_A2F
	add edx, '0'
	jmp .store

.is_A2F:
	sub edx, 10
	add edx, 'A'
.store:
	mov [ebx+edi], dl
	dec edi
	shr eax, 4
	mov edx, eax
	loop .16based_4bits

.ready_to_print:
	inc edi

.skip_prefix_0:
	cmp edi, 8
	je .full0

.go_on_skip:
	mov cl, [put_int_buffer+edi]
	inc edi
	cmp cl, '0'
	je .skip_prefix_0
	dec edi
	jmp .put_each_num

.full0:
	mov cl, '0'
.put_each_num:
	push ecx
	call put_char
	add esp, 4
	inc edi
	mov cl, [put_int_buffer+edi]
	cmp edi, 8
	jl .put_each_num
	popad
	ret

; 打印字符串
put_str:
	push ebx
	push ecx
	xor ecx, ecx
	mov ebx, [esp+12]

.goon:
	mov cl, [ebx]
	cmp cl, 0 ; 处理到字符串尾跳转
	jz .str_over

	push ecx ; 参数
	call put_char ; 调用函数打印字符
	add esp, 4 ; 指向下一个字符
	inc ebx
	jmp .goon

.str_over:
	pop ecx
	pop ebx
	ret

; 打印字符
put_char:
	pushad ; 将寄存器eax-edx-ecx-ebx-esp-ebp-esi-edi 压栈
	mov ax, SELECTOR_VIDEO
	mov gs, ax
	
	;获取当前光标的位置
	mov dx, 0x03d4
	mov al, 0x0e
	out dx, al
	mov dx, 0x03d5
	in al, dx ; 高8位
	mov ah, al

	mov dx, 0x03d4
	mov al, 0x0f
	out dx, al
	mov dx, 0x03d5
	in al, dx ; 低8位
	mov bx, ax ; bx光标位置的16位数

	mov ecx, [esp+36] ; 获取栈中的字符，4*8+调用函数返回地址4字节=36

	cmp cl, 0xd ; cr
	jz .is_carriage_return
	cmp cl, 0xa ; lf
	jz .is_line_feed
	cmp cl, 0x8 ; 退格键
	jz .is_backspace

	jmp .put_other

.is_backspace:
	dec bx
	shl bx, 1
	mov byte [gs:bx], 0x20
	inc bx
	mov byte [gs:bx], 0x07
	shr bx, 1
	jmp set_cursor

.put_other:
	shl bx, 1
	mov [gs:bx], cl
	inc bx
	mov byte [gs:bx], 0x07
	shr bx, 1
	inc bx
	cmp bx, 2000
	jl set_cursor

.is_line_feed:
.is_carriage_return:
	xor dx, dx
	mov ax, bx
	mov si, 80
	div si
	sub bx, dx

.is_carriage_return_end:
	add bx, 80
	cmp bx, 2000

.is_line_feed_end:
	jl set_cursor

.roll_screen:
	cld
	mov ecx, 960
	mov esi, 0xc00b80a0
	mov edi, 0xc00b8000
	rep movsd

	mov ebx, 3840
	mov ecx, 80

.cls:
	mov word [gs:ebx], 0x0720
	add ebx, 2
	loop .cls
	mov bx, 1920

; 设置光标
set_cursor:
	mov dx, 0x03d4
	mov al, 0x0e
	out dx, al
	mov dx, 0x03d5
	mov al, bh
	out dx, al

	mov dx, 0x03d4
	mov al, 0x0f
	out dx, al
	mov dx, 0x03d5
	mov al, bl
	out dx, al

.put_char_done:
	popad
	ret







